package com.xcity.game.skill.v2;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;

import org.slf4j.Logger;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.player.PlayerUtils;
import com.xcity.game.skill.Skill;
import com.xcity.game.skill.SkillService;
import com.xcity.game.skill.template.SkillTemplate;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.util.NumberUtils;

public class DefaultSkillV2 implements Skill, SkillEffector {

	protected int id;
	protected int level;
	protected byte unlocked;
	
	protected SkillTemplate template;
	protected SkillManagerV2 vm;
	protected Float[] params;
	protected int unlockStarLvl;
	
	public static final Logger LOG = SkillService.LOG;
	
	public DefaultSkillV2() {}
	
	public DefaultSkillV2(Player player, SkillTemplate template, int unlockStarLvl) {
		this(player.getSkillManager(), template, unlockStarLvl, PlayerUtils.getStarLevel(player));
	}
	
	public DefaultSkillV2(Employee employee, SkillTemplate template, int unlockStarLvl) {
		this(employee.getSkillManager(), template, unlockStarLvl, employee.getStarLvl());
	}
	
	private DefaultSkillV2(SkillManagerV2 vm, SkillTemplate template, int unlockStarLvl, int ownerStarLvl) {
		this.id = template.getId();
		this.level = 1;
		this.template = template;
		this.vm = vm;
		this.unlockStarLvl = unlockStarLvl;
		this.unlocked = (byte) (ownerStarLvl >= unlockStarLvl ? 1 : 0);
	}
	
	@Override
	public int getId() {
		return id;
	}
	
	public void setId(int id) {
		this.id = id;
	}
	
	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public byte getUnlocked() {
		return unlocked;
	}

	public void setUnlocked(byte unlocked) {
		this.unlocked = unlocked;
	}

	@JSONField(serialize = false)
	@Override
	public String getName() {
		return getTemplate().getName();
	}

	@JSONField(serialize = false)
	@Override
	public String getIcon() {
		return getTemplate().getIcon();
	}

	@JSONField(serialize = false)
	@Override
	public String getDesc() {
		String desc = getTemplate().getDesc();
		Object[] params = getParams();
		if (params != null && params.length > 0) {
			desc = MessageFormat.format(desc, params);
		}
		return desc;
	}

	@JSONField(serialize = false)
	@Override
	public SkillTemplate getTemplate() {
		return template != null ? template : (template = App.getApp().getServiceManager().get(TemplateService.class).get(SkillTemplate.class, id));
	}

	@JSONField(serialize = false)
	public SkillManagerV2 getVm() {
		return vm;
	}
	
	public void setVm(SkillManagerV2 vm) {
		this.vm = vm;
	}

	@JSONField(serialize = false)
	public Float[] getParams() {
		if (params == null) {
			params = getTemplate().getValues(level);
		}
		return params;
	}
	
	@JSONField(serialize = false)
	public boolean isUnlocked() {
		return unlocked == 1;
	}
	
	@JSONField(serialize = false)
	public int getUnlockStarLvl() {
		return unlockStarLvl;
	}

	public void setUnlockStarLvl(int unlockStarLvl) {
		this.unlockStarLvl = unlockStarLvl;
	}

	@Override
	public boolean addLevel(int val, String cause) {
		this.level += val;
		updateParams();
//		LOG.info("[SKILL LVLUP]ID[{}]OWNER[{}]SKILL[{}]OLD[{}]NEW[{}]CAUSE[{}]", 1);
		return true;
	}

	private SkillEffector effector;
	@Override
	public float enhance(CombatAttributeType type, float value) {
		return isUnlocked() ? getEffector().enhance(type, value) : 0f;
	}
	
	public void reset() {
		this.level = 1;
		updateParams();
	}
	
	private void updateParams() {
		Float[] params = getParams();
		SkillTemplate st = getTemplate();
		for (int i = 0; i < params.length; i++) {
			float val = st.getValue(i, this.level);
			if (val != (int) val) {
				String s = String.valueOf(val);
				if (NumberUtils.getDecimalDigit(s) > 1) {
					// 保留一位小数
					BigDecimal b = new BigDecimal(s).setScale(1, RoundingMode.DOWN);
					val = b.floatValue();
				}
			}
			params[i] = Float.valueOf(val);
		}
	}
	
	@JSONField(serialize = false)
	public SkillEffector getEffector() {
		if (effector == null) {
			effector = SkillEffectorFactory.create(this);
		}
		return effector;
	}

	@Override
	@JSONField(serialize = false)
	public CombatAttributeType[] getEnhanceTypes() {
		return getEffector().getEnhanceTypes();
	}

	@Override
	public float getParameter(int index) {
		Float[] vals = getParams();
		return index >= 0 && index < vals.length ? vals[index].floatValue() : 0f;
	}

}
